//
// Created by Administrator on 2025/2/25.
//

#ifndef THREADPOOL_THREADPOOL_H
#define THREADPOOL_THREADPOOL_H

#include <iostream>
#include <vector>
#include <queue>
#include <memory>
#include <atomic>
#include <mutex>
#include <condition_variable>
#include <functional>
#include "Thread.h"
#include "Any.h"


//todo 写配置文件
const int TASK_MAX_THRESHHOLD = 1024;

//线程池模式
enum PoolMode{
    MODE_FIXED,//固定数量的模式
    MODE_CACHED,//动态数量的模式
};

class Result;

//任务抽象基类
class Task{
public:
    Task();
    virtual ~Task();
    // 执行任务
    void exec();
    //设置返回值
    void setResult(Result* result);
    //用户可以自定义任意任务类型，从Task继承，重写run方法，实现自定义任务处理
    virtual Any run()=0;
private:
    Result* _result;
};


//线程池类
class ThreadPool {
public:
    ThreadPool();
    ~ThreadPool();
    //

    //设置线程池的工作模式
    void setMode(PoolMode mode);
    //开启线程池
    void start(int initThreadSize = 4);

    //设置任务队列的上限阈值
    void setTaskQueMaxThreshHold(int taskQueMaxThreshHold);
    //给线程池提供任务
    Result submitTask(std::shared_ptr<Task> sp);
    //禁止对线程池进行拷贝构造和赋值操作
    ThreadPool(const ThreadPool&) = delete;
    ThreadPool& operator=(const ThreadPool&) = delete;

private:
    //定义线程函数，线程执行需要线程函数
    void threadFunc();

private:
    std::vector<std::unique_ptr<Thread>> _threadVec;//线程容器，存放线程指针
    size_t _initThreadCount; //初始的线程个数

    //不能使用基类裸指针，用户若是传递一个临时指针，很可能任务队列就存放了已经析构的指针
    std::queue<std::shared_ptr<Task>> _taskQue;//任务队列
    std::atomic_uint _taskCount;//记录任务数量，++，--
    int _taskQueMaxThreshHold;//任务上限阈值

    //将来操作的都是任务队列，要确保线程安全机制
    std::mutex _taskQueMtx;//任务队列的互斥锁
    //池的基本设计--不空和不满--不空时可以消费，不满可以生产
    std::condition_variable _notFull;
    std::condition_variable _notEmpty;

    //当前线程池的工作模式
    PoolMode _poolMode;
    bool _isRunning;
};

// Result类，用于保存线程的返回值
class Result {
public:
    Result(std::shared_ptr<Task> task,bool isDone = true);
    ~Result();
    // 设置返回值
    void setValue(Any any);
    // 获取返回值
    Any get();
private:
    std::shared_ptr<Task> _task;
    Any _any;//要有any，保存返回的数据
    Semaphore _sem;//信号量，线程完成才可以设置获取结果
    std::atomic_bool _isDone;//是否完成
};
#endif //THREADPOOL_THREADPOOL_H
